﻿using System;
using System.Collections.Generic;
using Blazing.BusinessObjects.Products;
using System.BusinessObjects.Data;
using Iesi.Collections.Generic;
using Blazing.BusinessObjects.Tagging;
using Blazing.BusinessObjects.Cms;
using Blazing.BusinessObjects.Queries;
using System.Web;
using System.Linq;
using Blazing.BusinessObjects.eCommerce.Queries;
using Blazing.BusinessObjects.Assets;

namespace Blazing.WebFacade
{
    [System.ComponentModel.DataObject]
    public class ProductsController
    {
        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Delete, true)]
        public void DeleteProduct(Product obj)
        {
            obj.Delete();
            obj.Save(SaveMode.Flush);
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Insert, true)]
        public Product NewProduct(Product obj)
        {
            obj.Save(SaveMode.Flush);
            return obj;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, true)]
        public Product UpdateProduct(Product obj)
        {
            Product.Evict(obj.ID);

            ISet<TaxonomyTag> tagList = new HashedSet<TaxonomyTag>();
            if (obj != null)
            {
                foreach (TaxonomyTag tag in obj.TaxonomyTags)
                {
                    tagList.Add(TaxonomyTag.Load(tag.ID));
                }
            }
            obj.TaxonomyTags = tagList;

            obj.Save(SaveMode.Flush);
            return obj;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
        public IList<Product> GetProducts()
        {
            return Product.Search(NHibernate.Criterion.Order.Asc("Name"));
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
        public IList<Product> GetProductsByTag(List<TaxonomyTag> tag)
        {
            return Product.Search(QrySearchProductsByTaxonomyTags.Query(tag));
        }

        public Product GetProductFromPage(Contentpage page)
        {
            List<TaxonomyTag> tags = new List<TaxonomyTag>();
            foreach (TaxonomyTag tag in page.TaxonomyTags)
            {
                if (tag.Taxonomy.Name == "Products")
                {
                    tags.Add(tag);
                }
            }

            if (tags.Count > 0)
            {
                Product prod = Product.Fetch(QrySearchProductsByTaxonomyTags.Query(tags).SetMaxResults(1));
                if (prod != null)
                    return prod;
            }

            return null;
        }

        static object getProductHomepageSync = new object();
        public Contentpage GetProductHomepage(Product prod, Site site)
        {
            List<TaxonomyTag> tags = new List<TaxonomyTag>();
            Contentpage homepage = null;

            Func<int> loadAction = delegate
            {
                Contentpage home = null;
                foreach (TaxonomyTag tag in prod.TaxonomyTags)
                {
                    if (tag.Taxonomy.Name == "Products") //.TaxonomyType.Name == "Internal")
                    {
                        tags.Add(tag);
                    }
                }

                if (tags.Count > 0)
                {
                    Contentpage page = Contentpage.Fetch(QrySearchPagesByTaxonomyTags.Query(tags, site).SetMaxResults(1));
                    home = page;

                    while (home != null && home.ParentPage != null)
                        home = home.ParentPage;
                }

                return home != null ? home.ID : 0;
            };

            homepage = FacadeCacheManager.GetItemCache<Contentpage>(loadAction,
                arg0 => new PageController().GetPage(arg0),
                ref getProductHomepageSync,
                "GetProductHomepage", prod.ID, site.ID);

            return homepage;
        }

        static object getProductImagesSync = new object();
        public IList<Asset> GetProductImages(Product prod)
        {
            List<TaxonomyTag> tags = new List<TaxonomyTag>();
            IList<Asset> assets = new List<Asset>();

            foreach (TaxonomyTag tag in prod.TaxonomyTags)
            {
                if (tag.Taxonomy.Name == "Products")
                {
                    tags.Add(tag);
                }
            }

            if (tags.Count > 0)
            {
                assets = Asset.Search(QrySearchAssetsByTaxonomyTags.Query(tags, 1));
            }

            return assets;
        }

        public IList<Asset> GetProductImages(Product prod, IList<TaxonomyTag> extraTags)
        {
            List<TaxonomyTag> tags = new List<TaxonomyTag>();
            IList<Asset> assets = new List<Asset>();

            foreach (TaxonomyTag tag in prod.TaxonomyTags)
            {
                if (tag.Taxonomy.Name == "Products")
                {
                    tags.Add(tag);
                }
            }
            tags.AddRange(extraTags);

            if (tags.Count > 0)
            {
                assets = Asset.Search(QrySearchAssetsByTaxonomyTags.Query(tags, 1));
            }

            return assets;
        }

        public IList<Asset> GetProductImagesBySlugs(Product prod, string slugs)
        {
            if (prod == null)
                throw new ArgumentNullException("prod", "prod is null.");
            if (String.IsNullOrEmpty(slugs))
                throw new ArgumentException("slugs is null or empty.", "slugs");

            var tagController = new TaggingController();
            string[] tagSlugs = slugs.Split(',');
            IList<TaxonomyTag> tags = TaxonomyTag.Search(QrySearchTaxonomyTagsBySlugs.Query(new List<string>(tagSlugs)));

            var list = GetProductImages(prod, tags);
            return list;
        }

        public Blazing.BusinessObjects.Products.Order CurrentOrder
        {
            get
            {
                var order = HttpContext.Current.Session["CurrentOrder"] as Blazing.BusinessObjects.Products.Order;

                if (order == null)
                {
                    order = new Blazing.BusinessObjects.Products.Order();
                    HttpContext.Current.Session["CurrentOrder"] = order;
                }

                return order;
            }
            set
            {
                HttpContext.Current.Session["CurrentOrder"] = value;
            }
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select)]
        public IList<Product> GetShoppingCart()
        {
            var order = CurrentOrder as Blazing.BusinessObjects.Products.Order;
            return order.Items;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Delete)]
        public void DeleteFromShoppingCart(Product obj)
        {
            var order = CurrentOrder as Blazing.BusinessObjects.Products.Order;
            order.Items.Remove(order.Items.Last(i => i.ID == obj.ID));
            CurrentOrder = order;
        }

        public void AddProductToCart(Product item)
        {
            var order = CurrentOrder as Blazing.BusinessObjects.Products.Order;
            order.Items.Add(item);
            CurrentOrder = order;
        }

        public IList<TaxonomyTag> TagsAttachedToProducts(int taxonomyId)
        {
            return TaxonomyTag.Search(QrySearchTaxonomyTagsByTaxonomyAttachedToProducts.Query(taxonomyId));
        }
    }
}
